/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.service.table.impl;

import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Lists;
import com.je.common.base.DynaBean;
import com.je.common.base.constants.ConstantVars;
import com.je.common.base.constants.Enable;
import com.je.common.base.db.JEDatabase;
import com.je.common.base.service.CommonService;
import com.je.common.base.service.MetaService;
import com.je.common.base.service.rpc.BeanService;
import com.je.common.base.service.rpc.SystemSettingRpcService;
import com.je.common.base.util.DateUtils;
import com.je.common.base.util.StringUtil;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.meta.service.setting.MetaSystemSettingService;
import com.je.meta.service.table.MetaResFieldService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class MetaResFieldServiceImpl implements MetaResFieldService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private MetaService metaService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private MetaSystemSettingService systemSettingService;
    @Autowired
    private SystemSettingRpcService systemSettingRpcService;

    @Override
    public void buildDefault(DynaBean dynaBean) {
        String xtype = dynaBean.getStr("RESOURCEFIELD_XTYPE");
        String orderSql = " order by (CONVERT(int,replace(RESOURCEFIELD_CODE,'" + xtype + "_',''))) ASC ";
        if (ConstantVars.STR_ORACLE.equals(JEDatabase.getCurrentDatabase())
                || ConstantVars.STR_SHENTONG.equals(JEDatabase.getCurrentDatabase())
                || ConstantVars.STR_KINGBASEES.equals(JEDatabase.getCurrentDatabase())
                || ConstantVars.STR_DM.equals(JEDatabase.getCurrentDatabase())) {
            orderSql = " order by (to_number(replace(RESOURCEFIELD_CODE,'" + xtype + "_',''))) ASC ";
        } else if (ConstantVars.STR_MYSQL.equals(JEDatabase.getCurrentDatabase())
                || ConstantVars.STR_TIDB.equals(JEDatabase.getCurrentDatabase())) {
            orderSql = " order by (convert(replace(RESOURCEFIELD_CODE,'" + xtype + "_',''),SIGNED)) ASC ";
        }
        DynaBean funcInfo = metaService.selectOneByPk("JE_CORE_FUNCINFO", dynaBean.getStr("RESOURCEFIELD_FUNCINFO_ID"));
        List<DynaBean> fields = metaService.select("JE_CORE_RESOURCEFIELD", ConditionsWrapper.builder().apply(" AND RESOURCEFIELD_FUNCINFO_ID='" + dynaBean.getStr("RESOURCEFIELD_FUNCINFO_ID") + "' AND RESOURCEFIELD_XTYPE='" + xtype + "'" + orderSql));
        Integer index = 1;
        if (fields.size() > 0) {
            for (Integer i = 0; i < fields.size(); i++) {
                if (!(xtype + "_" + (i + 1)).equals(fields.get(i).getStr("RESOURCEFIELD_CODE"))) {
                    index = i + 1;
                    break;
                }
            }
            if (index == 1 && (xtype + "_" + fields.size()).equals(fields.get(fields.size() - 1).getStr("RESOURCEFIELD_CODE"))) {
                index = fields.size() + 1;
            }
        }
        dynaBean.set("RESOURCEFIELD_CODE", xtype + "_" + index);
        dynaBean.set("RESOURCEFIELD_NAME", dynaBean.getStr("RESOURCEFIELD_NAME") + index);
        dynaBean.set("SY_STATUS", Enable.TRUE);
        dynaBean.set("SY_CREATETIME", DateUtils.formatDate(new Date()));
        //所占行数
        dynaBean.set("RESOURCEFIELD_ROWSPAN", 1);
        //所占列数
        dynaBean.set("RESOURCEFIELD_COLSPAN", funcInfo.get("FUNCINFO_FORMCOLS"));
        //分组框列数
        dynaBean.set("RESOURCEFIELD_COLS", funcInfo.get("FUNCINFO_FORMCOLS"));

        dynaBean.set("RESOURCEFIELD_XTYPE", xtype);
        dynaBean.set("SY_ORDERINDEX", 0);
        //是否可用
        dynaBean.set("RESOURCEFIELD_DISABLED", "1");
        //是否隐藏
        dynaBean.set("RESOURCEFIELD_HIDDEN", "0");
        //是否可以为空
        dynaBean.set("RESOURCEFIELD_ALLOWBLANK", "1");
        //适用范围
        dynaBean.set("RESOURCEFIELD_USE_SCOPE", "ALL");
        if ("fieldset".equals(xtype)) {
            dynaBean.set("RESOURCEFIELD_BGCOLOR", "");
            JSONObject otherConfig = new JSONObject();
            otherConfig.put("borderTopColor", "");
            otherConfig.put("borderColor", StringUtil.getDefaultValue(systemSettingRpcService.findSettingValue("RESOURCEFIELD_BORDER_COLOR"), ""));
            otherConfig.put("titleBgColor", StringUtil.getDefaultValue(systemSettingRpcService.findSettingValue("RESOURCEFIELD_TITLEB_BGCOLOR"), ""));
            otherConfig.put("titleColor", StringUtil.getDefaultValue(systemSettingRpcService.findSettingValue("RESOURCEFIELD_TITLEB_COLOR"), ""));
            otherConfig.put("basicColor", "");
            otherConfig.put("bgColor", StringUtil.getDefaultValue(systemSettingRpcService.findSettingValue("RESOURCEFIELD_BGCOLOR"), ""));
            dynaBean.set("RESOURCEFIELD_OTHERCONFIG", otherConfig.toString());
            //快速定位
            dynaBean.set("RESOURCEFIELD_LOCATE", "1");
        }else if("childfuncfield".equals(xtype)){
            JSONObject otherConfig = new JSONObject();
            otherConfig.put("buttonAlign","right");
            otherConfig.put("remove","1");
            otherConfig.put("add","1");
            dynaBean.set("RESOURCEFIELD_OTHERCONFIG", otherConfig.toString());
        }
        commonService.buildModelCreateInfo(dynaBean);
    }

    @Override
    @Transactional
    public void doSync(DynaBean dynaBean) {
        ConditionsWrapper selectFieldCW = ConditionsWrapper.builder();
        selectFieldCW.eq("RESOURCEFIELD_FUNCINFO_ID", dynaBean.getStr("RESOURCEFIELD_FUNCINFO_ID"));
        if (StringUtil.isNotEmpty(dynaBean.getStr("RESOURCEFIELD_PLAN_ID"))) {
            selectFieldCW.eq("RESOURCEFIELD_PLAN_ID", dynaBean.getStr("RESOURCEFIELD_PLAN_ID"));
        }
        List<DynaBean> fieldList = metaService.select("JE_CORE_RESOURCEFIELD", selectFieldCW);
        ConditionsWrapper selectColumn = ConditionsWrapper.builder();
        selectColumn.eq("RESOURCECOLUMN_FUNCINFO_ID", dynaBean.getStr("RESOURCEFIELD_FUNCINFO_ID"));
        if (StringUtil.isNotEmpty(dynaBean.getStr("RESOURCECOLUMN_PLAN_ID"))) {
            selectColumn.eq("RESOURCECOLUMN_PLAN_ID", dynaBean.getStr("RESOURCECOLUMN_PLAN_ID"));
        }
        List<DynaBean> columnList = metaService.select("JE_CORE_RESOURCECOLUMN", selectColumn);
        if (fieldList.size() > 0 && columnList.size() > 0) {
            for (DynaBean rc : columnList) {
                for (DynaBean rf : fieldList) {
                    if (rf.get("RESOURCEFIELD_CODE").equals(rc.get("RESOURCECOLUMN_CODE"))) {
                        rf.set("SY_ORDERINDEX", rc.get("SY_ORDERINDEX"));
                        rf.set("RESOURCEFIELD_NAME", rc.get("RESOURCECOLUMN_NAME"));
                        rf.set("RESOURCEFIELD_HIDDEN", rc.get("RESOURCECOLUMN_HIDDEN"));
                        rf.set(BeanService.KEY_TABLE_CODE, "JE_CORE_RESOURCEFIELD");
                        metaService.update(rf);
                    }
                }
            }
        }
    }

    @Override
    @Transactional
    public DynaBean updateField(DynaBean dynaBean) {
        String readOnly = dynaBean.getStr("RESOURCEFIELD_READONLY");
        String tableCode = dynaBean.getStr(BeanService.KEY_TABLE_CODE);
        if ("1".equals(readOnly)) {
            String updateSql = "update " + tableCode + " set RESOURCEFIELD_EDITABLE='0' where RESOURCEFIELD_CODE='" + dynaBean.getStr("RESOURCEFIELD_CODE") + "' and RESOURCEFIELD_FUNCINFO_ID='" + dynaBean.getStr("RESOURCEFIELD_FUNCINFO_ID") + "'";
            metaService.executeSql(updateSql);
        }
        String resourcefieldMaxlength = dynaBean.get("RESOURCEFIELD_MAXLENGTH") == null ? "" : dynaBean.get("RESOURCEFIELD_MAXLENGTH").toString();
        if (StringUtil.isEmpty(resourcefieldMaxlength)) {
            dynaBean.set("RESOURCEFIELD_MAXLENGTH", 0);
        }
        metaService.update(dynaBean,ConditionsWrapper.builder().eq("JE_CORE_RESOURCEFIELD_ID",dynaBean.getStr("JE_CORE_RESOURCEFIELD_ID")));
        return dynaBean;
    }

    @Override
    @Transactional
    public String clearGroupFields(List<DynaBean> fields) {
        String funcId = "";
        for (DynaBean field : fields) {
            String xtype = field.getStr("RESOURCEFIELD_XTYPE");
            String code = field.getStr("RESOURCEFIELD_CODE");
            funcId = field.getStr("RESOURCEFIELD_FUNCINFO_ID");
            if ("fieldset".equals(xtype)) {
                String updateSql = "UPDATE JE_CORE_RESOURCEFIELD set RESOURCEFIELD_GROUPNAME='' where RESOURCEFIELD_GROUPNAME='" + code + "' and RESOURCEFIELD_FUNCINFO_ID ='" + field.getStr("RESOURCEFIELD_FUNCINFO_ID") + "'";
                metaService.executeSql(updateSql);
            }
        }
        return funcId;
    }

    @Override
    @Transactional
    public int doDicConfigSync() {
        //获取全部可编辑字典项配置
        List<DynaBean> allFields = metaService.select("JE_CORE_RESOURCEFIELD", ConditionsWrapper.builder()
                .apply(" AND RESOURCEFIELD_XTYPE in ('rgroup','cgroup','cbbfield','treessfield','treessareafield') AND INSTR(RESOURCEFIELD_OTHERCONFIG,'\"editDic\":\"1\"') > 0 "), "JE_CORE_RESOURCEFIELD_ID,RESOURCEFIELD_OTHERCONFIG");
        //切分 长度为1000
        List<List<DynaBean>> fieldsList = Lists.partition(allFields, 1000);
        for (List<DynaBean> fields : fieldsList) {
            List<String> fieldIds = Lists.newArrayList();
            //拼接update语句
            StringBuffer sql = new StringBuffer();
            sql.append(" UPDATE JE_CORE_RESOURCEFIELD SET RESOURCEFIELD_OTHERCONFIG =  CASE JE_CORE_RESOURCEFIELD_ID  ");
            for (DynaBean field : fields) {
                String fieldId = field.getStr("JE_CORE_RESOURCEFIELD_ID");
                String otherConfig = field.getStr("RESOURCEFIELD_OTHERCONFIG");

                //统一图标样式
                JSONObject config = JSONObject.parseObject(otherConfig);
                config.put("editDicIcon", "jeicon jeicon-pencil");
                config.put("editDicIconColor", "#EBEBEB");
                config.put("editDicIconHoverColor", "#386BD0");

                sql.append(" WHEN '" + fieldId + "' THEN '" + config.toString() + "' ");
                fieldIds.add(fieldId);
            }
            sql.append(" END WHERE JE_CORE_RESOURCEFIELD_ID in (" + StringUtil.buildArrayToString(fieldIds) + ")");
            //更新配置数据
            metaService.executeSql(sql.toString());
        }
        return allFields.size();
    }

    @Override
    @Transactional
    public int doFieldMaxLengthSync() {
        //表单字段最大长度 = 数据库字段长度 / ratio
        int ratio = 1;
        //获取全部可编辑字典项配置
        List<DynaBean> tables = metaService.select("JE_CORE_RESOURCETABLE", ConditionsWrapper.builder(), "JE_CORE_RESOURCETABLE_ID,RESOURCETABLE_TABLECODE");
        int errorCount = 0;
        //遍历表
        for (DynaBean table : tables) {
            String tableId = table.getStr("JE_CORE_RESOURCETABLE_ID");
            String tableName = table.getStr("RESOURCETABLE_TABLECODE");
            //查询表所有列
            List<DynaBean> columnInfos = metaService.select("JE_CORE_TABLECOLUMN", ConditionsWrapper.builder().apply(" AND TABLECOLUMN_TYPE like 'VARCHAR%' AND TABLECOLUMN_RESOURCETABLE_ID = '" + tableId + "'"), "TABLECOLUMN_CODE,TABLECOLUMN_TYPE,TABLECOLUMN_LENGTH");
            //list转map映射
            Map<String, DynaBean> columnInfoMap = columnInfos.stream().collect(Collectors.toMap(p -> p.getStr("TABLECOLUMN_CODE"), p -> p));

            //获取表对应的所有功能
            List<DynaBean> funcInfos = metaService.select("JE_CORE_FUNCINFO", ConditionsWrapper.builder().apply(StringUtil.format(" AND (FUNCINFO_CRUDTABLENAME = '{0}' or FUNCINFO_TABLENAME = '{0}')", tableName)), "JE_CORE_FUNCINFO_ID,FUNCINFO_FUNCCODE");
            for (DynaBean funcInfo : funcInfos) {
                try {
                    String funcInfoId = funcInfo.getStr("JE_CORE_FUNCINFO_ID");
                    //获取所有功能字段
                    List<DynaBean> resourceFields = metaService.select("JE_CORE_RESOURCEFIELD", ConditionsWrapper.builder().apply(StringUtil.format("AND RESOURCEFIELD_FUNCINFO_ID = '{0}' AND  RESOURCEFIELD_XTYPE IN ('textfield','textarea','textcode','numberfield')", funcInfoId),
                            "RESOURCEFIELD_CODE,RESOURCEFIELD_XTYPE,JE_CORE_RESOURCEFIELD_ID"));
                    List<String> fieldIds = Lists.newArrayList();
                    //拼接update语句
                    StringBuffer sql = new StringBuffer();
                    sql.append(" UPDATE JE_CORE_RESOURCEFIELD SET RESOURCEFIELD_MAXLENGTH =  CASE JE_CORE_RESOURCEFIELD_ID  ");

                    //遍历功能字段设置字段长度
                    for (DynaBean resourceField : resourceFields) {

                        String fieldId = resourceField.getStr("JE_CORE_RESOURCEFIELD_ID");
                        String type = resourceField.getStr("RESOURCEFIELD_XTYPE");
                        String code = resourceField.getStr("RESOURCEFIELD_CODE");

                        String columnLenghtStr = "";

                        //若等于 numberfield 则该字段为数字输入设置长度为15
                        if ("numberfield".equals(type)) {
                            columnLenghtStr = "15";
                        } else {
                            if (columnInfoMap.containsKey(code)) {
                                DynaBean columnInfo = columnInfoMap.get(code);
                                //字段类型
                                String columnType = columnInfo.getStr("TABLECOLUMN_TYPE");
                                //字段长度
                                columnLenghtStr = columnInfo.getStr("TABLECOLUMN_LENGTH");

                                if (!"VARCHAR".equalsIgnoreCase(columnType)) {
                                    columnLenghtStr = columnType.replaceAll("VARCHAR", "");
                                }
                            }
                        }
                        if (StringUtil.isEmpty(columnLenghtStr)) {
                            continue;
                        }

                        //计算长度
                        int columnLenght = Integer.parseInt(columnLenghtStr) / ratio;
                        sql.append(" WHEN '" + fieldId + "' THEN '" + columnLenght + "' ");
                        fieldIds.add(fieldId);
                    }
                    sql.append(" END WHERE JE_CORE_RESOURCEFIELD_ID in (" + StringUtil.buildArrayToString(fieldIds) + ")");
                    //更新字段最大长度
                    metaService.executeSql(sql.toString());
                } catch (Exception e) {
                    logger.info("功能【{}】表单字段最大长度设置失败!", funcInfo.getStr("FUNCINFO_FUNCCODE"));
                    e.printStackTrace();
                    errorCount++;
                }
            }
        }
        return errorCount;
    }

    @Override
    @Transactional
    public void doSyncWfInfo() {
//        List<DynaBean> processInfos = metaWorkflowService.selectByTableCodeAndNativeQuery("JE_CORE_PROCESSINFO", NativeQuery.build().eq("PROCESSINFO_LASTVERSION", "none"));
        List<DynaBean> processInfos = null;
        for (DynaBean process : processInfos) {
            String appInfos = process.getStr("PROCESSINFO_APPFUNCINFOS");
            List<DynaBean> processLasts = metaService.select("JE_CORE_PROCESSINFO", ConditionsWrapper.builder().ne("JE_CORE_PROCESSINFO_ID", process.getStr("JE_CORE_PROCESSINFO_ID")).eq("PROCESSINFO_PROCESSKEY", process.getStr("PROCESSINFO_PROCESSKEY")));
            for (DynaBean processLast : processLasts) {
                processLast.set("PROCESSINFO_APPFUNCINFOS", appInfos);
                metaService.update(processLast);
            }
        }
    }

    @Override
    public int doRemove(String ids) {
        List<DynaBean> beans = metaService.select("JE_CORE_RESOURCEFIELD", ConditionsWrapper.builder().apply(" AND JE_CORE_RESOURCEFIELD_ID IN (" + StringUtil.buildArrayToString(ids.split(",")) + ")"));
        if (beans != null && beans.size() > 0) {
            String RESOURCEFIELD_FUNCINFO_ID = beans.get(0).getStr("RESOURCEFIELD_FUNCINFO_ID");
            for (DynaBean item : beans) {
                String RESOURCEFIELD_XTYPE = item.getStr("RESOURCEFIELD_XTYPE");
                if ("fieldset".equals(RESOURCEFIELD_XTYPE)) {
                    String RESOURCEFIELD_CODE = item.getStr("RESOURCEFIELD_CODE");
                    metaService.executeSql("update je_core_resourcefield set RESOURCEFIELD_GROUPNAME=null where RESOURCEFIELD_GROUPNAME='" + RESOURCEFIELD_CODE + "' and RESOURCEFIELD_FUNCINFO_ID='" + RESOURCEFIELD_FUNCINFO_ID + "'");
                }
                metaService.delete("JE_CORE_RESOURCEFIELD", ConditionsWrapper.builder().eq("JE_CORE_RESOURCEFIELD_ID", item.get("JE_CORE_RESOURCEFIELD_ID")));
            }
            return beans.size();
        }
        return 0;
    }
}
